"""
Ele.me (饿了么) platform scraper implementation
"""
import re
import time
from typing import List, Optional
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException

from .base_scraper import BaseScraper
from ..models import RestaurantData
from ..config import config, PLATFORMS


class ElemeScraper(BaseScraper):
    """Scraper for Ele.me platform"""
    
    def __init__(self, database_manager):
        super().__init__("eleme", database_manager)
        self.base_url = PLATFORMS["eleme"]["base_url"]
        self.selectors = PLATFORMS["eleme"]["selectors"]
        
    def navigate_to_city(self, city: str) -> bool:
        """Navigate to Ele.me and set location to specified city"""
        try:
            self.logger.info(f"Navigating to Ele.me for city: {city}")
            
            # Load main page
            self.driver.get(self.base_url)
            self.random_delay(2, 4)
            
            # Handle location permission popup if it appears
            self._handle_location_popup()
            
            # Try to set location to the specified city
            if self._set_location(city):
                self.logger.info(f"Successfully set location to {city}")
                return True
            else:
                self.logger.warning(f"Failed to set location to {city}, proceeding anyway")
                return True  # Continue even if location setting fails
                
        except Exception as e:
            self.logger.error(f"Failed to navigate to city {city}: {e}")
            return False
            
    def _handle_location_popup(self):
        """Handle location permission popup"""
        try:
            # Look for common location popup elements
            location_popups = [
                "//button[contains(text(), '确定')]",
                "//button[contains(text(), '允许')]", 
                "//div[contains(@class, 'location-popup')]//button",
                "//div[contains(@class, 'permission')]//button"
            ]
            
            for popup_xpath in location_popups:
                try:
                    popup_button = self.safe_find_element(By.XPATH, popup_xpath, timeout=3)
                    if popup_button:
                        popup_button.click()
                        self.logger.info("Handled location popup")
                        self.random_delay(1, 2)
                        break
                except:
                    continue
                    
        except Exception as e:
            self.logger.debug(f"No location popup found or error handling it: {e}")
            
    def _set_location(self, city: str) -> bool:
        """Set location to specified city"""
        try:
            # Look for location/address input or button
            location_selectors = [
                "//input[contains(@placeholder, '地址') or contains(@placeholder, '位置')]",
                "//div[contains(@class, 'address')]//input",
                "//div[contains(@class, 'location')]//input",
                "//span[contains(@class, 'address-text')]",
                "//div[contains(@class, 'current-address')]"
            ]
            
            for selector in location_selectors:
                try:
                    location_element = self.safe_find_element(By.XPATH, selector, timeout=5)
                    if location_element:
                        # If it's an input, try to enter the city
                        if location_element.tag_name == 'input':
                            location_element.clear()
                            location_element.send_keys(city)
                            self.random_delay(1, 2)
                            
                            # Look for search results or confirmation
                            self._confirm_location_selection(city)
                            return True
                        else:
                            # If it's a clickable element, click it to open location selector
                            location_element.click()
                            self.random_delay(1, 2)
                            return self._select_city_from_list(city)
                            
                except Exception as e:
                    self.logger.debug(f"Location selector {selector} failed: {e}")
                    continue
                    
            return False
            
        except Exception as e:
            self.logger.error(f"Error setting location: {e}")
            return False
            
    def _confirm_location_selection(self, city: str):
        """Confirm location selection from dropdown"""
        try:
            # Look for location suggestions or confirmation buttons
            confirm_selectors = [
                f"//li[contains(text(), '{city}')]",
                f"//div[contains(text(), '{city}')]",
                "//button[contains(text(), '确认')]",
                "//button[contains(text(), '确定')]"
            ]
            
            for selector in confirm_selectors:
                confirm_element = self.safe_find_element(By.XPATH, selector, timeout=3)
                if confirm_element:
                    confirm_element.click()
                    self.random_delay(1, 2)
                    break
                    
        except Exception as e:
            self.logger.debug(f"Error confirming location: {e}")
            
    def _select_city_from_list(self, city: str) -> bool:
        """Select city from location list"""
        try:
            # Look for city in location list
            city_selectors = [
                f"//li[contains(text(), '{city}')]",
                f"//div[contains(@class, 'city-item')][contains(text(), '{city}')]",
                f"//span[contains(text(), '{city}')]"
            ]
            
            for selector in city_selectors:
                city_element = self.safe_find_element(By.XPATH, selector, timeout=5)
                if city_element:
                    city_element.click()
                    self.random_delay(1, 2)
                    return True
                    
            return False
            
        except Exception as e:
            self.logger.error(f"Error selecting city from list: {e}")
            return False
            
    def get_restaurant_urls(self, limit: int = None) -> List[str]:
        """Get restaurant URLs from the current page"""
        restaurant_urls = []
        limit = limit or config.MAX_RESTAURANTS_PER_CITY
        
        try:
            self.logger.info("Collecting restaurant URLs")
            
            # Scroll and load more restaurants
            self._scroll_and_load_restaurants(limit)
            
            # Find restaurant links
            restaurant_selectors = [
                "//a[contains(@href, '/shop/')]",
                "//div[contains(@class, 'restaurant')]//a",
                "//li[contains(@class, 'restaurant-item')]//a",
                "//div[contains(@class, 'shop-item')]//a"
            ]
            
            for selector in restaurant_selectors:
                elements = self.safe_find_elements(By.XPATH, selector)
                for element in elements:
                    href = self.safe_get_attribute(element, 'href')
                    if href and '/shop/' in href:
                        full_url = href if href.startswith('http') else self.base_url.rstrip('/') + href
                        if full_url not in restaurant_urls:
                            restaurant_urls.append(full_url)
                            
                if restaurant_urls:
                    break
                    
            # Limit results
            if limit:
                restaurant_urls = restaurant_urls[:limit]
                
            self.logger.info(f"Found {len(restaurant_urls)} restaurant URLs")
            return restaurant_urls
            
        except Exception as e:
            self.logger.error(f"Error getting restaurant URLs: {e}")
            return restaurant_urls
            
    def _scroll_and_load_restaurants(self, target_count: int):
        """Scroll page to load more restaurants"""
        try:
            last_height = self.driver.execute_script("return document.body.scrollHeight")
            loaded_count = 0
            scroll_attempts = 0
            max_scroll_attempts = 10
            
            while loaded_count < target_count and scroll_attempts < max_scroll_attempts:
                # Scroll down
                self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
                self.random_delay(2, 3)
                
                # Check if new content loaded
                new_height = self.driver.execute_script("return document.body.scrollHeight")
                
                # Count current restaurants
                restaurant_elements = self.safe_find_elements(By.XPATH, "//a[contains(@href, '/shop/')]")
                loaded_count = len(restaurant_elements)
                
                if new_height == last_height:
                    scroll_attempts += 1
                else:
                    scroll_attempts = 0
                    
                last_height = new_height
                self.logger.debug(f"Loaded {loaded_count} restaurants, scroll attempt {scroll_attempts}")
                
        except Exception as e:
            self.logger.error(f"Error scrolling page: {e}")
            
    def extract_restaurant_data(self, url: str) -> Optional[RestaurantData]:
        """Extract restaurant data from restaurant page"""
        try:
            self.logger.debug(f"Extracting data from: {url}")
            
            # Navigate to restaurant page
            self.driver.get(url)
            self.random_delay(2, 4)
            
            # Extract data fields
            name = self._extract_restaurant_name()
            category = self._extract_restaurant_category()
            location = self._extract_restaurant_location()
            price_range = self._extract_price_range()
            phone = self._extract_phone_number()
            
            # Validate required fields
            if not name:
                self.logger.warning(f"No restaurant name found for {url}")
                return None
                
            restaurant_data = RestaurantData(
                name=name,
                category=category,
                location=location,
                price_range=price_range,
                phone=phone,
                platform=self.platform_name,
                url=url
            )
            
            self.logger.debug(f"Extracted data: {restaurant_data.dict()}")
            return restaurant_data
            
        except Exception as e:
            self.logger.error(f"Error extracting restaurant data from {url}: {e}")
            return None
            
    def _extract_restaurant_name(self) -> str:
        """Extract restaurant name"""
        name_selectors = [
            "//h1[contains(@class, 'restaurant-name')]",
            "//div[contains(@class, 'shop-name')]//h1",
            "//div[contains(@class, 'shop-title')]",
            "//h1",
            "//div[contains(@class, 'name')]"
        ]
        
        for selector in name_selectors:
            element = self.safe_find_element(By.XPATH, selector, timeout=5)
            if element:
                name = self.safe_get_text(element)
                if name:
                    return name
                    
        return ""
        
    def _extract_restaurant_category(self) -> str:
        """Extract restaurant category/cuisine type"""
        category_selectors = [
            "//span[contains(@class, 'category')]",
            "//div[contains(@class, 'cuisine')]",
            "//span[contains(text(), '菜系')]/../span[2]",
            "//div[contains(@class, 'shop-info')]//span"
        ]
        
        for selector in category_selectors:
            element = self.safe_find_element(By.XPATH, selector, timeout=3)
            if element:
                category = self.safe_get_text(element)
                if category and not any(x in category for x in ['评分', '配送', '时间', '费']):
                    return category
                    
        return ""
        
    def _extract_restaurant_location(self) -> str:
        """Extract restaurant location/address"""
        location_selectors = [
            "//div[contains(@class, 'address')]",
            "//span[contains(@class, 'location')]",
            "//div[contains(@class, 'shop-address')]",
            "//div[contains(text(), '地址')]/../div[2]"
        ]
        
        for selector in location_selectors:
            element = self.safe_find_element(By.XPATH, selector, timeout=3)
            if element:
                location = self.safe_get_text(element)
                if location:
                    return location
                    
        return ""
        
    def _extract_price_range(self) -> str:
        """Extract price range/average order value"""
        price_selectors = [
            "//span[contains(text(), '人均')]",
            "//div[contains(@class, 'price')]",
            "//span[contains(@class, 'average-price')]",
            "//div[contains(text(), '￥')]"
        ]
        
        for selector in price_selectors:
            element = self.safe_find_element(By.XPATH, selector, timeout=3)
            if element:
                price_text = self.safe_get_text(element)
                if price_text and ('￥' in price_text or '元' in price_text):
                    return price_text
                    
        return ""
        
    def _extract_phone_number(self) -> str:
        """Extract restaurant phone number"""
        phone_selectors = [
            "//a[contains(@href, 'tel:')]",
            "//span[contains(@class, 'phone')]",
            "//div[contains(@class, 'contact')]//span",
            "//div[contains(text(), '电话')]/../div[2]"
        ]
        
        for selector in phone_selectors:
            element = self.safe_find_element(By.XPATH, selector, timeout=3)
            if element:
                if 'tel:' in self.safe_get_attribute(element, 'href'):
                    phone = self.safe_get_attribute(element, 'href').replace('tel:', '')
                else:
                    phone = self.safe_get_text(element)
                    
                # Clean and validate phone number
                if phone:
                    phone = re.sub(r'[^\d-]', '', phone)
                    if len(phone) >= 7:
                        return phone
                        
        return ""
